home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************************************
- *
- *
- * ObjectMacZapp -- a standard Mac OOP application template
- *
- *
- *
- * ZMenuBar.cpp -- the menubar manager object
- *
- *
- *
- *
- *
- * © 1996, Graham Cox
- *
- *
- *
- *
- *************************************************************************************************/
-
-
- #include "MacZoop.h"
- #include "ZCommander.h"
-
- extern ZCommander* gCurHandler;
-
- /*--------------------------------*** DESTRUCTOR ***---------------------------------*/
-
-
- ZMenuBar::~ZMenuBar()
- {
- if ( theMenuCmds )
- ForgetObject( theMenuCmds );
-
- if ( theMenus )
- ForgetObject( theMenus );
-
- ReleaseResource((Handle) mBarH );
- }
-
-
- /*--------------------------------*** INITMENUBAR ***--------------------------------*/
- /*
- initialise the menubar from a MBAR resource
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::InitMenuBar()
- {
- // create an array for holding our command info
-
- FailNIL( theMenuCmds = new ZArray( sizeof( MenuCmd )));
- FailNIL( theMenus = new ZArray( sizeof( MenuInfRec )));
-
- mbCount = 0;
- miSeed = 1;
- wmMenuID = 0;
-
- // load the MBAR resource
-
- mBarH = (short**) GetResource( 'MBAR', mBarID );
- FailOSErr( ResError());
-
- HNoPurge((Handle) mBarH );
-
- // read in menus from the MBAR resource
-
- LoadMenus();
-
- HPurge((Handle) mBarH );
-
- // add the standard items (DA's) to the Apple menu
-
- AppendStdItems( kAppleMenuID );
-
- menuCheckChar = checkMark;
-
- // note how many items are in the help menu so we can correctly
- // identify any items we have added
-
- MenuHandle helpMenuH;
-
- FailOSErr( HMGetHelpMenuHandle( &helpMenuH ));
- mHelpOffset = CountMenuItems( helpMenuH );
- }
-
-
- /*-------------------------------*** CLICKMENUBAR ***--------------------------------*/
- /*
- handle mouse click in the menubar
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::ClickMenuBar( const Point mousePt )
- {
- long mSelect;
- MenuCmd* mCmd;
-
- // initially disable all menu items
-
- DimMenus();
-
- // ask the command chain to reenable the relevant menu items
-
- if ( gCurHandler )
- gCurHandler->UpdateMenus();
-
- // now track and select the menus
-
- mSelect = TrackMenuBar( mousePt );
-
- // dispatch the command
-
- DispatchCommand( mSelect );
- }
-
-
- /*-------------------------------*** TRACKMENUBAR ***--------------------------------*/
- /*
- track the menubar, returning the item chosen.
- ---------------------------------------------------------------------------------------*/
-
- long ZMenuBar::TrackMenuBar( const Point mouse )
- {
- return MenuSelect( mouse );
- }
-
-
- /*------------------------------*** DISPATCHCOMMAND ***------------------------------*/
- /*
- look up the command and send it up the chain
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::DispatchCommand( const long mSelect )
- {
- MenuCmd mCmd;
- GrafPtr savePort;
-
- GetPort( &savePort );
-
- // if an item was chosen, look up the command and send it up the chain
-
- mCmd.theCmd = noCommand;
-
- if ( HiWord( mSelect) != 0 && gCurHandler )
- {
- // if the nominated windows menu, handle the window selection
-
- if ( HiWord( mSelect ) == wmMenuID )
- gWindowManager->SelectWindowFromMenu( LoWord( mSelect ));
-
- FindMCmd( mSelect, &mCmd );
-
- if ( mCmd.theCmd != parentCmd )
- {
- // if the command was found, pass it up the chain. If not found, we still pass it
- // up the chain, but this time as the direct menuID and itemID chosen. Commander
- // classes can choose which of the two methods (or perhaps both?) to adopt.
-
- if ( mCmd.theCmd != noCommand )
- gCurHandler->HandleCommand( mCmd.theCmd );
- else
- gCurHandler->HandleCommand( HiWord( mSelect ), LoWord( mSelect ));
- }
-
- SetPort( savePort );
- SetTitleHilite( 0, FALSE );
- }
- }
-
-
- /*---------------------------------*** ENABLECMD ***---------------------------------*/
- /*
- enable the menu item associated with the command
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::EnableCommand( const long cmd )
- {
- short m = 0, i = 0;
-
- FindCommand( cmd, &m, &i );
-
- if ( m && i )
- EnableCommand( m, i );
- }
-
- /*---------------------------------*** ENABLECMD ***---------------------------------*/
-
- void ZMenuBar::EnableCommand( const short menuID, const short itemID )
- {
- MenuHandle mH = FindMenuID( menuID );
-
- if ( mH )
- EnableItem( mH, itemID );
- }
-
- /*---------------------------------*** DISABLECMD ***--------------------------------*/
- /*
- disable the menu item associated with the command
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::DisableCommand( const long cmd )
- {
- short m = 0, i = 0;
-
- FindCommand( cmd, &m, &i );
-
- if ( m && i )
- DisableCommand( m, i );
- }
-
- /*---------------------------------*** DISABLECMD ***--------------------------------*/
-
- void ZMenuBar::DisableCommand( const short menuID, const short itemID )
- {
- MenuHandle mH = FindMenuID( menuID );
-
- if ( mH )
- DisableItem( mH, itemID );
- }
-
-
- /*--------------------------------*** CHECKCOMMAND ***-------------------------------*/
- /*
- check the menu command on or off.
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::CheckCommand( const long cmd, const Boolean checkOnOff )
- {
- short m = 0, i = 0;
-
- FindCommand( cmd, &m, &i );
-
- if ( m && i )
- CheckCommand( m, i, checkOnOff );
- }
-
-
- /*--------------------------------*** CHECKCOMMAND ***-------------------------------*/
-
- void ZMenuBar::CheckCommand( const short menuID, const short itemID, const Boolean checkOnOff )
- {
- MenuHandle mH = FindMenuID( menuID );
-
- if ( mH )
- SetItemMark( mH, itemID, checkOnOff? menuCheckChar : noMark );
- }
-
-
- /*--------------------------------*** CHECKCOMMAND ***-------------------------------*/
-
- void ZMenuBar::CheckCommand( const short menuID, Str255 itemString, const Boolean checkOnOff )
- {
- // check the item with the text matching that passed (not case sensitive)
-
- MenuHandle mH = FindMenuID( menuID );
- Str255 iMatch;
-
- if ( mH )
- {
- short m = CountMenuItems( mH );
-
- do
- {
- GetMenuItemText( mH, m, iMatch );
-
- if ( EqualString( itemString, iMatch, FALSE, TRUE ))
- {
- SetItemMark( mH, m, checkOnOff? menuCheckChar : noMark );
- break;
- }
- }
- while( --m );
- }
- }
-
-
- /*-------------------------------*** SETCOMMANDTEXT ***------------------------------*/
- /*
- set the text of a menu item to the desired string. Can be accessed by command or item.
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::SetCommandText( const long cmd, Str255 aText )
- {
- short m = 0, i = 0;
-
- FindCommand( cmd, &m, &i );
-
- if ( m && i )
- SetCommandText( m, i, aText );
- }
-
-
- /*-------------------------------*** SETCOMMANDTEXT ***------------------------------*/
-
- void ZMenuBar::SetCommandText( const short menuID, const short itemID, Str255 aText )
- {
- MenuHandle mH;
-
- mH = FindMenuID( menuID );
-
- if ( mH )
- SetMenuItemText( mH, itemID, aText );
- }
-
-
- /*-------------------------------*** SETCOMMANDTEXT ***------------------------------*/
-
- void ZMenuBar::SetCommandText( const long cmd, const short strListID, const short strIndex )
- {
- Str255 aText;
-
- GetIndString( aText, strListID, strIndex );
- if ( aText[0] > 0 )
- SetCommandText( cmd, aText );
- }
-
-
- /*-------------------------------*** SETCOMMANDTEXT ***------------------------------*/
-
- void ZMenuBar::SetCommandText( const short menuID, const short itemID, const short strListID, const short strIndex )
- {
- Str255 aText;
-
- GetIndString( aText, strListID, strIndex );
- if ( aText[0] > 0 )
- SetCommandText( menuID, itemID, aText );
- }
-
-
- /*-----------------------------*** NOMINATEWINDOWSMENU ***---------------------------*/
- /*
- This method can be used to set up an automatic "Windows" menu. To do this, call this
- method once your bar is built. This will nominate the menu with the ID passed as the
- Windows menu. Any items in the menu already will be retained and work as normal. As
- windows are added and deleted in the window manager, this will maintain the menu for you.
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::NominateWindowsMenu( const short menuID )
- {
- if ( wmMenuID == 0 )
- {
- MenuHandle mH = FindMenuID( menuID );
-
- if ( mH )
- {
- wmMenuID = menuID;
-
- SetMenuDimming( menuID, disableCmdsOnly );
-
- // we need to work hand-in-hand with the window manager to
- // keep track of the windows. The Window Manager is best placed to
- // do all this, so we simply hand off the menu to it.
-
- gWindowManager->SetWindowsMenu( mH );
- }
- }
- }
-
-
- /*-------------------------------*** INSERTHELPITEM ***------------------------------*/
- /*
- append the text to the help menu, and return the item number of the resulting item. To
- process this item, override HandleCommand and look for kHMHelpMenuID and the item returned
- from this method.
- ---------------------------------------------------------------------------------------*/
-
- short ZMenuBar::AppendHelpItem( Str255 itemText )
- {
- short i;
- MenuHandle helpMenuH;
-
- FailOSErr( HMGetHelpMenuHandle( &helpMenuH ));
-
- i = mHelpOffset + 1;
- AppendMenu( helpMenuH, itemText );
-
- return i;
- }
-
-
- /*------------------------------*** APPENDMENUTOBAR ***------------------------------*/
- /*
- This can be called to add menus "on the fly" into the bar. This reads a menu from a
- MENU or CMNU resource, parses its comands and inserts the menu. Menus can only be added
- to the end of the bar. You need to call UpdateMenuBar after this or a series of these.
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::AppendMenuToBar( const short menuID )
- {
- Handle temp;
-
- temp = GetResource( 'CMNU', menuID );
-
- if ( temp )
- {
- LoadCMNUMenu( menuID );
- ReleaseResource( temp );
- }
- else
- LoadMenu( menuID );
-
- mbCount++;
- }
-
- /*-----------------------------*** REMOVEMENUFROMBAR ***-----------------------------*/
- /*
- This can be called to remove a menu added with the above routine. You need to call
- UpdateMenuBar after this or a series of these.
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::RemoveMenuFromBar( const short menuID )
- {
- MenuHandle mH;
-
- FailNILParam( mH = GetMenuHandle( menuID ));
-
- // remove the command entries for this menu and any submenus it is the parent of.
-
- UnloadMenu( mH );
- mbCount--;
- }
-
-
-
- /*---------------------------------*** LOADMENUS ***---------------------------------*/
- /*
- for each menu in the MBAR, call LoadMenu. This will deal with hierarchical menus, etc.
- This method assumes mBarH is valid, and won't be purged.
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::LoadMenus( const Boolean autoInstall )
- {
- short i, menuID;
- Handle temp;
-
- // how many menus in MBAR resource? This is first item in resource.
-
- mbCount = (*mBarH)[0];
-
- // iterate through, looking for MENU or CMNU resources
-
- for ( i = 1; i <= mbCount; i++ )
- {
- menuID = (*mBarH)[i];
-
- // if CMNU resource is available, use that. Otherwise, use MENU resource,
- // possibly parsing it for command numbers
-
- temp = GetResource( 'CMNU', menuID );
-
- if ( temp )
- {
- LoadCMNUMenu( menuID, FALSE, autoInstall );
- ReleaseResource( temp );
- }
- else
- LoadMenu( menuID, FALSE, autoInstall );
-
- }
- }
-
- /*----------------------------------*** DIMMENUS ***---------------------------------*/
- /*
- dim all of the menu items, according to their flags.
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::DimMenus()
- {
- // This originally operated by walking the low-memory global menuList, but that does
- // not work when 3rd party extensions install extra menus. Thus we now use our private
- // list of menus to do this operation so we only affect our own menus.
-
- short i;
- MenuInfRec mRec;
-
- for ( i = 1; i <= mbCount; i++ )
- {
- // find this menu in our list, and dim it according to the
- // flags there. (Thanks to Jean-Yves Pochez for the improvements to this method)
-
- mRec.macMenu = NULL;
- theMenus->GetArrayItem( &mRec, i );
-
- if ( mRec.macMenu )
- {
- // menu is in our list, so dim it
-
- PredimMenu( mRec.macMenu );
- }
- }
-
- // if auto Windows menu in use, set that up as well
-
- if ( wmMenuID > 0 )
- gWindowManager->BuildWindowsMenu();
- }
-
-
- /*-------------------------------*** SETMENUDIMMING ***------------------------------*/
- /*
- set the dimming options for a particular menu. By default, all menus are dimmed auto-
- matically, but if you don't want them dimmed, or partially dimmed, call this with the
- required options.
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::SetMenuDimming( const short menuID, const DimmingOptions dimOpts )
- {
- MenuInfRec mr;
- Boolean bUpdate;
-
- mr.macMenu = NULL;
-
- FindMenuInfo( menuID, &mr );
-
- if ( mr.macMenu )
- {
- // if this call will change the state of the dimTitle flag, we need to cause an
- // update to the menubar so that the user sees the change
-
- bUpdate = (( mr.mDimming ^ dimOpts ) & dimTitle ) != 0;
-
- mr.mDimming = dimOpts;
- theMenus->SetArrayItem( &mr, mr.mIndex );
-
- // update the bar if necessary
-
- if ( bUpdate )
- {
- // enable or disable title item
-
- if ( dimOpts & dimTitle )
- (*mr.macMenu)->enableFlags &= 0xFFFFFFFE;
- else
- (*mr.macMenu)->enableFlags |= 1;
-
- UpdateMenuBar();
- }
- }
- }
-
-
- /*----------------------------------*** LOADMENU ***---------------------------------*/
- /*
- can be called recursively- try to load the menu with the ID and any submenus it refers
- to. If MENU resources are not found, try CMNU resources.
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::LoadMenu( const short menuID, Boolean isHMenu, Boolean autoInstall )
- {
- short i, mCount, cmdChar, subID;
- MenuHandle mH;
- MenuCmd mCmd;
- MenuInfRec mRec;
- Str255 iText;
-
- FailNILRes( mH = GetMenu( menuID ));
-
- // set up info record for this menu
-
- mRec.menuID = menuID;
- mRec.mIndex = miSeed++;
- mRec.macMenu = mH;
- mRec.mDimming = dimCommands;
- mRec.mIsResource = TRUE;
-
- theMenus->AppendItem( &mRec );
-
- // look through the menu for submenus, and recursively add them
-
- mCount = CountMenuItems( mH );
-
- for( i = 1; i <= mCount; i++ )
- {
- GetMenuItemText( mH, i, iText );
-
- if ( iText[1] != '-' )
- {
- // make a command entry for the item
-
- mCmd.menuID = menuID;
- mCmd.itemID = i;
- mCmd.macMenu = mH;
-
- ParseMenuItem( iText, &mCmd.theCmd );
-
- // menus created using GetMenu are resources, CMNU are not. This is flagged so
- // we can dispose of it correctly.
-
- mCmd.cmdFlags = autoUnCheck | ( isHMenu? 0 : isPrimaryMenu ) | menuIsResource;
- mCmd.subMenuID = 0;
-
- SetMenuItemText( mH, i, iText );
- GetItemCmd( mH, i, &cmdChar );
-
- if ( cmdChar == hMenuCmd )
- {
- // has a submenu, so load it:
-
- GetItemMark( mH, i, &subID );
-
- // need to determine if submenu is a MENU or CMNU resource:
-
- Handle cmnuH;
-
- cmnuH = GetResource( 'CMNU', subID );
-
- if ( cmnuH )
- {
- LoadCMNUMenu( subID, TRUE, autoInstall );
- ReleaseResource( cmnuH );
- }
- else
- LoadMenu( subID, TRUE, autoInstall );
-
- mCmd.subMenuID = subID;
- mCmd.theCmd = parentCmd;
- }
-
- theMenuCmds->AppendItem( &mCmd );
- }
- }
-
- // add the menu to the system list
-
- if ( autoInstall )
- InsertMenu( mH, isHMenu? hierMenu : 0 );
- }
-
- /*--------------------------------*** LOADCMNUMENU ***-------------------------------*/
- /*
- ditto for CMNU resources- this can parse that format of resource.
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::LoadCMNUMenu( const short menuID, Boolean isHMenu, Boolean autoInstall )
- {
- CMNUResHdl cH;
- MenuCmd mCmd;
- MenuInfRec mRec;
- MenuHandle mH;
- Ptr cmP, cmItemText;
- short itemID;
-
- cH = ( CMNUResHdl ) GetResource( 'CMNU', menuID );
-
- if ( cH )
- {
- // we need to do two things with this menu- a) make a normal menu handle that
- // can be inserted into the menu manager list, and b) a set of menuCmd records
- // so that we can look up the command when an item is chosen.
-
- FailNIL( mH = NewMenu( menuID, (ConstStr255Param) &(*cH)->mTitle ));
-
- // set up info record for this menu
-
- mRec.menuID = menuID;
- mRec.mIndex = miSeed++;
- mRec.macMenu = mH;
- mRec.mDimming = dimCommands;
- mRec.mIsResource = FALSE;
-
- theMenus->AppendItem( &mRec );
-
- HLock((Handle) cH );
-
- // we need to iterate through the items in the CMNU and build our two structures
- // as needed. To do this efficiently, we lock the handle and keep a running pointer.
-
- cmItemText = cmP = &(*cH)->mTitle + (*cH)->mTitle + 1;
- itemID = 0;
-
- // we're now at the start of the first item's text. We now scan through each item
- // building both the real menu and the command structure
-
- while( *cmItemText != 0 )
- {
- itemID++;
-
- cmP += *cmItemText + 1; // point to top of "interesting" info
-
- // add text of item, making sure meta-characters are ignored. Note that
- // a dividing line still works correctly
-
- AppendMenu( mH, "\px" );
- SetMenuItemText( mH, itemID, (ConstStr255Param) cmItemText );
-
- // add command entry if not a dividing line
-
- if ( cmItemText[1] != '-' )
- {
- // make menu item match info
-
- SetItemIcon ( mH, itemID, ((CMNUEntryPtr) cmP)->iconID );
- SetItemCmd ( mH, itemID, ((CMNUEntryPtr) cmP)->keyEqu );
- SetItemMark ( mH, itemID, ((CMNUEntryPtr) cmP)->markChar );
- SetItemStyle( mH, itemID, ((CMNUEntryPtr) cmP)->iStyle );
-
- mCmd.menuID = menuID;
- mCmd.itemID = itemID;
- mCmd.subMenuID = 0;
- mCmd.macMenu = mH;
- mCmd.cmdFlags = autoUnCheck | ( isHMenu? 0 : isPrimaryMenu );
- mCmd.theCmd = noCommand;
-
- // if there's a sub-menu, we'll need to find and load it too. This involves
- // a recursion to this function or to LoadMenu.
-
- if (((CMNUEntryPtr) cmP)->keyEqu == hMenuCmd )
- {
- mCmd.subMenuID = ((CMNUEntryPtr) cmP)->markChar;
-
- // is this a CMNU or a MENU resource?
-
- Handle cmnuH = GetResource( 'CMNU', mCmd.subMenuID );
-
- if ( cmnuH )
- {
- LoadCMNUMenu( mCmd.subMenuID, TRUE, autoInstall );
- ReleaseResource( cmnuH );
- }
- else
- LoadMenu( mCmd.subMenuID, TRUE, autoInstall );
-
- mCmd.theCmd = parentCmd;
- }
- else
- {
- // set up the command entry for the item. The command number
- // may follow a pad byte if it would otherwise be at an odd address, so the
- // data lies 4 or 5 bytes away from where cmP is now:
-
- if ((unsigned long) cmP & 1 )
- mCmd.theCmd = *(long*)( cmP + sizeof( CMNUEntry ) + 1 );
- else
- mCmd.theCmd = *(long*)( cmP + sizeof( CMNUEntry ));
- }
- // add the item to our command array
-
- theMenuCmds->AppendItem( &mCmd );
- }
-
- // set the pointers to the next item. This is 8 or 9 bytes away depending on
- // whether the resulting address is odd or even
-
- cmP += 8;
- if ((unsigned long) cmP & 1 )
- cmP++;
-
- cmItemText = cmP;
- }
-
- HUnlock((Handle) cH );
-
- // insert the menu we just built into the system list
-
- if ( autoInstall )
- InsertMenu( mH, isHMenu? hierMenu : 0 );
- }
- }
-
-
- /*---------------------------------*** UNLOADMENU ***--------------------------------*/
- /*
- removes this menu from the command list and un-inserts itself. It also calls itself to
- deal with its submenus. Called by RemoveMenuFromBar. Use with care.
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::UnloadMenu( MenuHandle mH )
- {
- long m;
- MenuCmd mCmd;
- Boolean resStatus = FALSE;
- Boolean isResMenu = FALSE;
-
- for( m = theMenuCmds->CountItems(); m > 0; m-- )
- {
- theMenuCmds->GetArrayItem( &mCmd, m );
-
- // if this is one pertaining to the menu, delete it from the array. Also
- // if its a parent item, call this again to delete the submenu too.
-
- if ( mH == mCmd.macMenu )
- {
- theMenuCmds->DeleteItem( m );
-
- // is this a parent?
-
- if ( mCmd.theCmd == parentCmd &&
- mCmd.subMenuID != 0 )
- {
- // yes, so recurse and delete that too
-
- MenuHandle smH = GetMenuHandle( mCmd.subMenuID );
-
- if ( smH )
- UnloadMenu( smH );
- }
-
- if ( !resStatus )
- {
- isResMenu = ( mCmd.cmdFlags & menuIsResource ) == menuIsResource;
- resStatus = TRUE;
- }
- }
- }
- // remove the menu from the system menu list
-
- DeleteMenu((*mH)->menuID );
-
- // dispose or release the menu handle according to whether
- // it was a resource or not
-
- if ( isResMenu )
- ReleaseResource((Handle) mH );
- else
- DisposeMenu( mH );
- }
-
- /*---------------------------------*** PREDIMMENU ***--------------------------------*/
- /*
- can be called recursively- dim this menu and any submenus it owns.
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::PredimMenu( MenuHandle theMenu )
- {
- short m, i, cmd, subID;
- MenuInfRec mi;
-
- if ( theMenu )
- {
- // initially set all items to be dimmed except the title ( we make one
- // exception- the apple menu only has the first item dimmed );
-
- if ((*theMenu)->menuID == kAppleMenuID )
- (*theMenu)->enableFlags = 0xFFFFFFF9;
- else
- {
- // get the info rec for this menu
-
- FindMenuInfo((*theMenu)->menuID, &mi );
-
- // dim items according to dimming flags except title
- // if title already dimmed, it is not re-enabled here.
-
- if (( mi.mDimming & 0x0F ) != neverDim )
- (*theMenu)->enableFlags &= 0x00000001;
-
- // look through the items for submenus
-
- m = CountMenuItems( theMenu );
-
- for( i = 1; i <= m; i++ )
- {
- GetItemCmd( theMenu, i, &cmd );
-
- if ( cmd == hMenuCmd )
- {
- // Enable the parent item if permitted
-
- EnableItem( theMenu, i );
- GetItemMark( theMenu, i, &subID );
-
- // find the sub-menu
-
- MenuHandle smMenu;
-
- smMenu = FindMenuID( subID );
-
- // dim the submenu
-
- PredimMenu( smMenu );
- }
- else
- {
- // if the item has no command and we don't want these dimming, enable it
-
- if ( mi.mDimming & dimCommands )
- {
- MenuCmd mc;
-
- mc.theCmd = 0;
- FindMCmd((((long)(*theMenu)->menuID ) << 16 ) | i, &mc );
-
- if ( mc.theCmd == 0 )
- EnableItem( theMenu, i );
- }
- // if the item is checked, uncheck it
-
- GetItemMark( theMenu, i, &cmd );
-
- if ( cmd != noMark )
- SetItemMark( theMenu, i, noMark );
- }
- }
- }
- }
- }
-
- /*-------------------------------*** PARSEMENUITEM ***-------------------------------*/
- /*
- extract command info from the item for TCL-style menu items
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::ParseMenuItem( Str255 iText, long* aCmd )
- {
- *aCmd = noCommand;
-
- // a valid command is associated with the item by appending a hash sysmbol (#),
- // followed by the command number as a string. Here we extract the number and
- // modify the string to exclude it.
-
- unsigned char i = 1;
- Str15 subStr;
-
- // search for # char
-
- while((iText[i] != '#') && (i < iText[0]))
- i++;
-
- if ( i < iText[0] )
- {
- // extract substring which is command number in string form
-
- BlockMoveData( &iText[i + 1], &subStr[1], iText[0] - i );
- subStr[0] = iText[0] - i;
-
- StringToNum( subStr, aCmd );
-
- // truncate string
-
- iText[0] = i - 1;
- }
- }
-
- /*------------------------------*** APPENDSTDITEMS ***-------------------------------*/
- /*
- appends DA names or FONT names to the menu
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::AppendStdItems( const short menuID, const short iType )
- {
- MenuHandle mH;
-
- mH = FindMenuID( menuID );
-
- if ( mH )
- AppendResMenu( mH, ( iType == appendDANames )? 'DRVR' : 'FONT' );
- }
-
-
- /*----------------------------------*** FINDMCMD ***---------------------------------*/
- /*
- find the command entry associated with the mSelection value.
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::FindMCmd( const long mSelect, MenuCmd* aCmd )
- {
- long m;
- MenuCmd mCmd;
-
- for( m = 1; m <= theMenuCmds->CountItems(); m++ )
- {
- theMenuCmds->GetArrayItem( &mCmd, m );
-
- // is this the one we want?
-
- if ( HiWord( mSelect ) == mCmd.menuID &&
- LoWord( mSelect ) == mCmd.itemID )
- {
- *aCmd = mCmd;
- break;
- }
- }
- }
-
-
- /*--------------------------------*** FINDCOMMAND ***--------------------------------*/
- /*
- inverse operation- given a command, return the original menu item and ID.
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::FindCommand( const long cmd, short* menuID, short* itemID )
- {
- long m;
- MenuCmd mCmd;
-
- for( m = 1; m <= theMenuCmds->CountItems(); m++ )
- {
- theMenuCmds->GetArrayItem( &mCmd, m );
-
- // is this the one we want?
-
- if ( cmd == mCmd.theCmd )
- {
- *menuID = mCmd.menuID;
- *itemID = mCmd.itemID;
- break;
- }
- }
- }
-
-
- /*------------------------------*** SETTITLEHILITE ***-------------------------------*/
- /*
- set the menu title hilite on or off
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::SetTitleHilite( const short menuID, const Boolean state )
- {
- if ( state )
- HiliteMenu( menuID );
- else
- HiliteMenu( 0 );
- }
-
-
- /*--------------------------------*** FINDMENUID ***---------------------------------*/
- /*
- returns the handle of the menu with the given ID, even if it has not been inserted into
- the system list. This can only find menus that belong to this bar object however.
- ---------------------------------------------------------------------------------------*/
-
- MenuHandle ZMenuBar::FindMenuID( const short menuID )
- {
- // returns the handle of the menu with the given ID. This works whether or not the menu
- // was actually installed in the system menu list. If so, we use the toolbox call. If not
- // we use the slightly slower method of looking through our private array of commands to
- // locate the menu.
-
- MenuInfRec mRec;
-
- mRec.macMenu = GetMenuHandle( menuID );
-
- if ( mRec.macMenu == NULL )
- FindMenuInfo( menuID, &mRec );
-
- return mRec.macMenu;
- }
-
-
- /*-------------------------------*** FINDMENUINFO ***--------------------------------*/
- /*
- returns the info record forthe given menu ID. This info is used to determine the right
- dimming and disposal behaviour for the menu.
- ---------------------------------------------------------------------------------------*/
-
- void ZMenuBar::FindMenuInfo( const short menuID, MenuInfRec* mRec )
- {
- short n, i;
- MenuInfRec mr;
-
- n = theMenus->CountItems();
-
- for( i = 1; i<= n; i++ )
- {
- theMenus->GetArrayItem( &mr, i );
-
- if ( mr.menuID == menuID )
- {
- *mRec = mr;
- break;
- }
- }
- }
-
-